package com.niiwoo.civet.trade.service.local.kaola;


import com.alibaba.fastjson.JSON;
import com.niiwoo.civet.trade.dto.kaola.request.ApplyRequest;
import com.niiwoo.civet.trade.dto.kaola.request.BankCardChangeRequest;
import com.niiwoo.civet.trade.dto.kaola.request.CompensationRequest;
import com.niiwoo.civet.trade.dto.kaola.request.GetRepayResultRequest;
import com.niiwoo.civet.trade.dto.kaola.request.OverdueRepaymentRequest;
import com.niiwoo.civet.trade.dto.kaola.request.PayCompensationNotifyRequest;
import com.niiwoo.civet.trade.dto.kaola.request.PreRepaymentRequest;
import com.niiwoo.civet.trade.dto.kaola.request.ReceiveRepayPlanRequest;
import com.niiwoo.civet.trade.dto.kaola.request.RepaymentRequest;
import com.niiwoo.civet.trade.dto.kaola.response.ApplyResponse;
import com.niiwoo.civet.trade.dto.kaola.response.BaseResponse;
import com.niiwoo.civet.trade.dto.kaola.response.CompensationResponse;
import com.niiwoo.civet.trade.dto.kaola.response.GetOrderStatResponse;
import com.niiwoo.civet.trade.dto.kaola.response.GetRepayResultResponse;
import com.niiwoo.civet.trade.dto.kaola.response.PayCompensationNotifyResponse;
import com.niiwoo.civet.trade.dto.kaola.response.PreRepaymentResponse;
import com.niiwoo.civet.trade.dto.kaola.response.ReceiveRepayPlanResponse;
import com.niiwoo.civet.trade.dto.kaola.response.RepaymentResponse;
import com.niiwoo.civet.trade.enums.kaola.KaoLaLiCaiRequestEnum;
import com.niiwoo.civet.trade.property.KaoLaLiCaiProperties;
import com.niiwoo.civet.trade.utils.koala.AES;
import com.niiwoo.tripod.base.component.AsyncHttpClients;
import com.niiwoo.tripod.base.exception.EncryptException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.concurrent.FutureCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 考拉网关接口实现
 * @author lichuanzhi
 * @date 2017-12-26 14:01
 */

@Slf4j
@Service
@EnableConfigurationProperties(KaoLaLiCaiProperties.class)
public class KaoLaLiCaiRequestServiceImpl implements KaoLaLiCaiRequestService{

    @Autowired
    private KaoLaLiCaiProperties kaoLaLiCaiProperties;

    @Autowired
    private AsyncHttpClients asyncHttpClients;

    @Override
    public GetOrderStatResponse getOrderStat(Long projectId, String orderId) {
        Map<String,Object> paramsMap = new HashMap<>(16);
        paramsMap.put("loan_order_id",orderId);
        paramsMap.put("subject_id",String.valueOf(projectId));
        return this.commonCall(KaoLaLiCaiRequestEnum.GET_ORDER_STAT,paramsMap,GetOrderStatResponse.class);
    }

    @Override
    public PreRepaymentResponse preRepayment(PreRepaymentRequest preRepaymentRequest) {
        return this.commonCall(KaoLaLiCaiRequestEnum.PRE_REPAYMENT,preRepaymentRequest,PreRepaymentResponse.class);
    }

    @Override
    public RepaymentResponse repayment(RepaymentRequest repaymentRequest) {
        return this.commonCall(KaoLaLiCaiRequestEnum.REPAYMENT,repaymentRequest,RepaymentResponse.class);
    }

    @Override
    public RepaymentResponse overdueRepayment(OverdueRepaymentRequest repaymentRequest) {
        return this.commonCall(KaoLaLiCaiRequestEnum.OVERDUE_REPAYMENT,repaymentRequest,RepaymentResponse.class);
    }

    @Override
    public BaseResponse bankCardChange(BankCardChangeRequest request) {
        return this.commonCall(KaoLaLiCaiRequestEnum.BANK_CARD_CHANGE,request,BaseResponse.class);
    }

    @Override
	public ApplyResponse apply(ApplyRequest applyRequest) {
    	return this.commonCall(KaoLaLiCaiRequestEnum.APPLY,applyRequest,ApplyResponse.class);
	}
    
    @Override
	public CompensationResponse compensation(CompensationRequest request) {
    	return this.commonCall(KaoLaLiCaiRequestEnum.APPLY,request,CompensationResponse.class);
	}
    
    @Override
	public GetRepayResultResponse getRepayResult(GetRepayResultRequest request) {
    	return this.commonCall(KaoLaLiCaiRequestEnum.GET_REPAY_RESULT,request,GetRepayResultResponse.class);
	}

    @Override
    public ReceiveRepayPlanResponse receiveRepayPlan(ReceiveRepayPlanRequest request) {
        return this.commonCall(KaoLaLiCaiRequestEnum.RECEIVE_REPAY_PLAN,request,ReceiveRepayPlanResponse.class);
    }

    @Override
    public PayCompensationNotifyResponse payCompensationNotify(PayCompensationNotifyRequest request) {
        return this.commonCall(KaoLaLiCaiRequestEnum.NOTIFY,request,PayCompensationNotifyResponse.class);
    }

    private <T extends BaseResponse,R> T commonCall(KaoLaLiCaiRequestEnum requestEnum, R r, Class<T> clazz){
        String secretReqStr;
        String paramStr;
        String responseStr;
        Map<String,String> jsonObject = new HashMap<>(16);

        //业务请求参数
        paramStr = JSON.toJSONString(r);

        log.info("考拉理财-{} oriRequest:{}",requestEnum.getDesc(),paramStr);

        //加密业务请求参数
        try{
            secretReqStr = AES.Encrypt(paramStr, kaoLaLiCaiProperties.getAesKey(), kaoLaLiCaiProperties.getAesIv());
        }catch(Exception e){
            log.error("KaoLaLiCaiRequestServiceImpl Encrypt Exception",e);
            throw new EncryptException("考拉报文加密异常",e);
        }

        //封装完整请求报文
        jsonObject.put("platform_id", kaoLaLiCaiProperties.getPlatformId());
        jsonObject.put("data",secretReqStr);
        log.info("考拉理财-{} request:{}",requestEnum.getDesc(),jsonObject);

        try{
            responseStr = this.doPost(kaoLaLiCaiProperties.getGateway().concat(requestEnum.getPath()),jsonObject).get();
        }catch (Exception e){
            log.error("KaoLaLiCaiRequestServiceImpl Http Exception",e);
            throw new RuntimeException("考拉接口请求异常",e);
        }
        log.info("考拉理财-{} response:{}",requestEnum.getDesc(),responseStr);
        return JSON.parseObject(responseStr,clazz);
    }

    private CompletableFuture<String> doPost(String url,Object params) {
        final CompletableFuture<String> future = new CompletableFuture<>();
        asyncHttpClients.restPost(url,params, new FutureCallback<HttpResponse>() {
            @Override
            public void completed(HttpResponse result) {
                try {
                    future.complete(asyncHttpClients.responseForPlain("UTF-8",result));
                } catch (Exception e) {
                    future.completeExceptionally(e);
                }
            }

            @Override
            public void failed(Exception ex) {
                future.completeExceptionally(ex);
            }

            @Override
            public void cancelled() {
                future.cancel(true);
            }
        });
        return future;
    }

}
